package com.mxpio.erp.workshop.policy.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.mxpio.erp.common.enums.*;
import com.mxpio.erp.common.inventory.entity.FeedPlanNotice;
import com.mxpio.erp.common.inventory.entity.FeedPlanNoticeLine;
import com.mxpio.erp.common.inventory.entity.SupplyChain;
import com.mxpio.erp.common.jpa.model.NoticeLine;
import com.mxpio.erp.common.jpa.model.Order;
import com.mxpio.erp.common.jpa.model.OrderLineKey;
import com.mxpio.erp.common.order.policy.AbstractBizOrderPolicy;
import com.mxpio.erp.common.order.policy.OrderContext;
import com.mxpio.erp.common.order.service.OrderLineService;
import com.mxpio.erp.common.purchase.entity.Supply;
import com.mxpio.erp.common.technology.entity.Item;
import com.mxpio.erp.common.technology.entity.ItemPlanProp;
import com.mxpio.erp.common.vo.NoticeClassVo;
import com.mxpio.erp.common.vo.OrderExcuteLineVo;
import com.mxpio.erp.common.workshop.entity.*;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.security.util.SecurityUtils;
import org.apache.commons.collections4.CollectionUtils;

/**
 * 生产订单领/退/补料策略
 * @author mxpio
 *
 */
public class DefaultPickingMoPolicy extends AbstractBizOrderPolicy {
	
	private List<OrderExcuteLineVo> orderExcuteVos;
	
	// 退料 -1，补料 2， 领料 1
	private String type;

	private OrderLineService orderLineService;
	
	public DefaultPickingMoPolicy(List<OrderExcuteLineVo> orderExcuteVos, String type, OrderLineService orderLineService) {
		this.orderExcuteVos = orderExcuteVos;
		this.type = type;
		this.orderLineService = orderLineService;
	}
	
	@Override
	public void execute(OrderContext context) {
		// TODO 领/退/补策略
		
	}
	
	@Override
	public OrderContext config(OrderContext context) {
		context.setOrderExcuteVos(orderExcuteVos);
		context.setNoticeClass(MoPickingNotice.class);
		if(NoticeStatusEnums.NoticeType.MO_M_IN.getCode().equals(type)){//MO_M_IN("15", "生产退料"),
			context.setAccessType(OrderEnums.AccessType.IN.getCode());
			context.setPickingType(NoticeStatusEnums.NoticeType.MO_M_IN.getCode());
		}else if(NoticeStatusEnums.NoticeType.MO_M_OUT.getCode().equals(type)){//	MO_M_OUT("41", "生产领料"),
			context.setAccessType(OrderEnums.AccessType.OUT.getCode());
			context.setPickingType(NoticeStatusEnums.NoticeType.MO_M_OUT.getCode());
		}else{
			context.setAccessType(OrderEnums.AccessType.OUT.getCode());
			context.setPickingType(NoticeStatusEnums.NoticeType.MO_M_REOUT.getCode());//MO_M_REOUT("42", "生产补料"),
		}
		
		return context;
	}

	@Override
	public void apply(OrderContext context) {//重写apply方法,把生产订单主单中的字段写入对应通知单
		if(beforeExecute(context)) {
			execute(context);
			ManufactureOrder order = (ManufactureOrder) context.getEntity();
			List<OrderExcuteLineVo> orderExcuteVos = context.getOrderExcuteVos();

			Set<String> itemCodeSet = orderExcuteVos.stream().map(OrderExcuteLineVo::getItemCode).collect(Collectors.toSet());
			List<Item> itemList = JpaUtil.linq(Item.class).in("itemCode", itemCodeSet).list();
			Map<Object, Item> itemMap = JpaUtil.index(itemList, "itemCode");

			List<ItemPlanProp> itemPlanPropList = JpaUtil.linq(ItemPlanProp.class).equal("propType", "item").in("code", itemCodeSet).list();
			Map<String, ItemPlanProp> itemPlanPropMap = JpaUtil.index(itemPlanPropList, "code");

			String[] accessTypes = context.getAccessType().split(",");
			for(String accessType : accessTypes){
				// 遍历执行行 生成通知单
				Map<String, MoPickingNotice> noticeMap = new HashMap<>();
				Map<String,List<OrderExcuteLineVo>> voMap = new HashMap<>();
				//jit物料
				List<OrderExcuteLineVo> jitVos = new ArrayList<>();
				//非jit物料
				List<OrderExcuteLineVo> unJitVos = new ArrayList<>();
				if (NoticeStatusEnums.NoticeType.MO_M_OUT.getCode().equals(context.getPickingType())
						||NoticeStatusEnums.NoticeType.MO_M_REOUT.getCode().equals(context.getPickingType())){
					for(OrderExcuteLineVo vo : orderExcuteVos) {
						//只考虑领料、补料这两种通知单类型，且是出库操作
						if (OrderEnums.AccessType.OUT.getCode().equals(accessType)
								&& itemPlanPropMap.containsKey(vo.getItemCode())
								&& ItemEnums.FeedingMode.JIT.getTypeCode().equals(itemPlanPropMap.get(vo.getItemCode()).getFeedingMode())){
							jitVos.add(vo);
						}else{
							unJitVos.add(vo);
						}
					}
				}
				//jit为空，则走之前默认逻辑
				if (jitVos.size()==0){
					for(OrderExcuteLineVo orderExcuteVo : orderExcuteVos) {
						MoPickingNotice notice = noticeMap.get(orderExcuteVo.getWhCode());
						if(notice == null) {
							notice = new MoPickingNotice();
							//关联生产订单业务字段
							notice.setProductItemCode(order.getProductItemCode());
							notice.setProductItemName(order.getProductItemName());
							notice.setOrderQuantity(order.getOrderQuantity());
							notice.setProductDrawingNo(order.getProductDrawingNo());
							notice.setMainWorkshop(order.getMainWorkshop());

							notice.setBizOrderNo(order.getBizNo());
							notice.setNoticeDate(new Date());
							notice.setWhCode(orderExcuteVo.getWhCode());
							notice.setAccessType(accessType);
							notice.setPickingType(context.getPickingType());
							notice.setNoticeStatus(NoticeStatusEnums.NoticeStatus.CREATE.getStatusCode());
							noticeMap.put(orderExcuteVo.getWhCode(), notice);
							voMap.put(orderExcuteVo.getWhCode(), new ArrayList<OrderExcuteLineVo>());
						}
						voMap.get(orderExcuteVo.getWhCode()).add(orderExcuteVo);
					}
					// 生成通知单明细
					for(Map.Entry<String,MoPickingNotice> entry : noticeMap.entrySet()) {
						MoPickingNotice notice = entry.getValue();
						JpaUtil.save(notice);
						int lineNo = 0;
						for(OrderExcuteLineVo vo : voMap.get(entry.getKey())) {
							lineNo++;
							NoticeLine line = notice.createLine(vo);
							line.setLineNo(lineNo+"");
							if (itemMap.containsKey(vo.getItemCode())){
								Item item = itemMap.get(vo.getItemCode());
								line.setItemName(item.getItemName());
								line.setItemSpec(item.getItemSpec());
								line.setUnitCode(item.getUnitCode());
								line.setDrawingNo(item.getDrawingNo());
							}
							JpaUtil.save(line);
						}
					}
				}else{
					//需要处理jit
					//有jit数据，但存在非jit明细的数据
					if (unJitVos.size()>0){
						for(OrderExcuteLineVo orderExcuteVo : unJitVos) {
							MoPickingNotice notice = noticeMap.get(orderExcuteVo.getWhCode());
							if(notice == null) {
								notice = new MoPickingNotice();
								//关联生产订单业务字段
								notice.setProductItemCode(order.getProductItemCode());
								notice.setProductItemName(order.getProductItemName());
								notice.setOrderQuantity(order.getOrderQuantity());
								notice.setProductDrawingNo(order.getProductDrawingNo());
								notice.setMainWorkshop(order.getMainWorkshop());

								notice.setBizOrderNo(order.getBizNo());
								notice.setNoticeDate(new Date());
								notice.setWhCode(orderExcuteVo.getWhCode());
								notice.setAccessType(accessType);
								notice.setPickingType(context.getPickingType());
								notice.setNoticeStatus(NoticeStatusEnums.NoticeStatus.CREATE.getStatusCode());
								noticeMap.put(orderExcuteVo.getWhCode(), notice);
								voMap.put(orderExcuteVo.getWhCode(), new ArrayList<OrderExcuteLineVo>());
							}
							voMap.get(orderExcuteVo.getWhCode()).add(orderExcuteVo);
						}
						// 生成通知单明细
						for(Map.Entry<String,MoPickingNotice> entry : noticeMap.entrySet()) {
							MoPickingNotice notice = entry.getValue();
							JpaUtil.save(notice);
							int lineNo = 0;
							for(OrderExcuteLineVo vo : voMap.get(entry.getKey())) {
								lineNo++;
								NoticeLine line = notice.createLine(vo);
								line.setLineNo(lineNo+"");
								if (itemMap.containsKey(vo.getItemCode())){
									Item item = itemMap.get(vo.getItemCode());
									line.setItemName(item.getItemName());
									line.setItemSpec(item.getItemSpec());
									line.setUnitCode(item.getUnitCode());
									line.setDrawingNo(item.getDrawingNo());
								}
								JpaUtil.save(line);
							}
						}
					}
					//jit物料
					// 遍历执行行 生成jit通知单
					for(OrderExcuteLineVo orderExcuteVo : jitVos) {
						SupplyChain one = JpaUtil.linq(SupplyChain.class).collect("pnCode", Supply.class, "pnCode").equal("itemCode", orderExcuteVo.getItemCode()).equal("defaultSupply", CommonEnums.YesNo.YES.getCode()).findOne();
						//统一按单行来拆，包括领料通知单
						MoPickingNotice notice = new MoPickingNotice();
						//关联生产订单业务字段
						notice.setProductItemCode(order.getProductItemCode());
						notice.setProductItemName(order.getProductItemName());
						notice.setOrderQuantity(order.getOrderQuantity());
						notice.setProductDrawingNo(order.getProductDrawingNo());
						notice.setMainWorkshop(order.getMainWorkshop());

						notice.setBizOrderNo(order.getBizNo());
						notice.setNoticeDate(new Date());
						notice.setWhCode(orderExcuteVo.getWhCode());
						notice.setAccessType(accessType);
						notice.setPickingType(context.getPickingType());
						notice.setNoticeStatus(NoticeStatusEnums.NoticeStatus.CREATE.getStatusCode());
						JpaUtil.save(notice);

						NoticeLine line = notice.createLine(orderExcuteVo);
						line.setLineNo("1");
						if (itemMap.containsKey(orderExcuteVo.getItemCode())) {
							Item item = itemMap.get(orderExcuteVo.getItemCode());
							line.setItemName(item.getItemName());
							line.setItemSpec(item.getItemSpec());
							line.setUnitCode(item.getUnitCode());
							line.setDrawingNo(item.getDrawingNo());
						}
						JpaUtil.save(line);

						//同时新增 送货计划
						FeedPlanNotice feedPlanNotice = new FeedPlanNotice();
						feedPlanNotice.setSourcePickingNoticeNo(line.getNoticeNo());
						feedPlanNotice.setWhCode(notice.getWhCode());
						feedPlanNotice.setNoticeStatus(NoticeStatusEnums.NoticeStatus.DRAFT.getStatusCode());
						feedPlanNotice.setNoticeDate(new Date());
						feedPlanNotice.setAccessType("in");
						feedPlanNotice.setPickingType(NoticeStatusEnums.NoticeType.FP_IN.getCode());
						feedPlanNotice.setBizOrderNo(order.getBizNo());
						//生产订单主表字段
						feedPlanNotice.setProductItemCode(order.getProductItemCode());
						feedPlanNotice.setProductItemName(order.getProductItemName());
						feedPlanNotice.setProductDrawingNo(order.getProductDrawingNo());
						if (one != null) {
							feedPlanNotice.setPnCode(one.getPnCode());
							feedPlanNotice.setPnName(one.getSupply().getPnName());
						}
						JpaUtil.save(feedPlanNotice);

						//查询生产订单bom
						OrderLineKey lineKey = new OrderLineKey();
						lineKey.setLineNo(orderExcuteVo.getBizOrderlineNo());
						lineKey.setBizNo(order.getBizNo());
						ManufactureOrderItem dbMoLine = JpaUtil.getOne(ManufactureOrderItem.class, lineKey);

						FeedPlanNoticeLine feedPlanNoticeLine = new FeedPlanNoticeLine();
						feedPlanNoticeLine.setNoticeNo(feedPlanNotice.getNoticeNo());
						feedPlanNoticeLine.setSourcePickingNoticeNo(line.getNoticeNo());
						feedPlanNoticeLine.setSourcePickingNoticeLineNo(line.getLineNo());
						feedPlanNoticeLine.setItemCode(line.getItemCode());
						feedPlanNoticeLine.setItemName(line.getItemName());
						feedPlanNoticeLine.setItemSpec(line.getItemSpec());
						feedPlanNoticeLine.setUnitCode(line.getUnitCode());
						feedPlanNoticeLine.setDrawingNo(line.getDrawingNo());
						feedPlanNoticeLine.setQuantity(line.getQuantity());
						feedPlanNoticeLine.setSort("1");
						feedPlanNoticeLine.setLineNo("1");
						feedPlanNoticeLine.setOriginBizNo(order.getBizNo());
						feedPlanNoticeLine.setOriginBizLineNo(line.getOriginBizLineNo());
						//冗余展示字段
						feedPlanNoticeLine.setMaterialBrand(dbMoLine.getMaterialBrand());
						feedPlanNoticeLine.setMaterialType(dbMoLine.getMaterialType());
						feedPlanNoticeLine.setMakeLength(dbMoLine.getMakeLength());
						feedPlanNoticeLine.setMakeArea(dbMoLine.getMakeArea());
						feedPlanNoticeLine.setMakeNum(dbMoLine.getMakeNum());

						JpaUtil.save(feedPlanNoticeLine);
					}
						/* //不再分组合并，统一按单条拆分。防止修改计划供应商，导致计划执行时，明细物料可能产生的送检和免检两种情况共存问题
						if (one==null || one.getInQualityControl().equals(CommonEnums.YesNo.YES.getCode())){
							MoPickingNotice notice = new MoPickingNotice();
							//关联生产订单业务字段
							notice.setProductItemCode(order.getProductItemCode());
							notice.setProductItemName(order.getProductItemName());
							notice.setOrderQuantity(order.getOrderQuantity());
							notice.setProductDrawingNo(order.getProductDrawingNo());
							notice.setMainWorkshop(order.getMainWorkshop());

							notice.setBizOrderNo(order.getBizNo());
							notice.setNoticeDate(new Date());
							notice.setWhCode(orderExcuteVo.getWhCode());
							notice.setAccessType(accessType);
							notice.setPickingType(context.getPickingType());
							notice.setNoticeStatus(NoticeStatusEnums.NoticeStatus.CREATE.getStatusCode());
							JpaUtil.save(notice);

							NoticeLine line = notice.createLine(orderExcuteVo);
							line.setLineNo("1");
							if (itemMap.containsKey(orderExcuteVo.getItemCode())){
								Item item = itemMap.get(orderExcuteVo.getItemCode());
								line.setItemName(item.getItemName());
								line.setItemSpec(item.getItemSpec());
								line.setUnitCode(item.getUnitCode());
								line.setDrawingNo(item.getDrawingNo());
							}
							JpaUtil.save(line);

							//同时新增 送货计划
							FeedPlanNotice feedPlanNotice = new FeedPlanNotice();
							feedPlanNotice.setSourcePickingNoticeNo(line.getNoticeNo());
							feedPlanNotice.setWhCode(notice.getWhCode());
							feedPlanNotice.setNoticeStatus(NoticeStatusEnums.NoticeStatus.DRAFT.getStatusCode());
							feedPlanNotice.setNoticeDate(new Date());
							feedPlanNotice.setAccessType("in");
							feedPlanNotice.setPickingType(NoticeStatusEnums.NoticeType.FP_IN.getCode());
							feedPlanNotice.setBizOrderNo(order.getBizNo());
							if (one!=null){
								feedPlanNotice.setPnCode(one.getPnCode());
								feedPlanNotice.setPnName(one.getSupply().getPnName());
							}
							JpaUtil.save(feedPlanNotice);

							FeedPlanNoticeLine feedPlanNoticeLine = new FeedPlanNoticeLine();
							feedPlanNoticeLine.setNoticeNo(feedPlanNotice.getNoticeNo());
							feedPlanNoticeLine.setSourcePickingNoticeNo(line.getNoticeNo());
							feedPlanNoticeLine.setSourcePickingNoticeLineNo(line.getLineNo());
							feedPlanNoticeLine.setItemCode(line.getItemCode());
							feedPlanNoticeLine.setItemName(line.getItemName());
							feedPlanNoticeLine.setItemSpec(line.getItemSpec());
							feedPlanNoticeLine.setUnitCode(line.getUnitCode());
							feedPlanNoticeLine.setDrawingNo(line.getDrawingNo());
							feedPlanNoticeLine.setQuantity(line.getQuantity());
							feedPlanNoticeLine.setSort("1");
							feedPlanNoticeLine.setLineNo("1");
							JpaUtil.save(feedPlanNoticeLine);
						}else{
							orderExcuteVo.setSupplyChain(one);
							jitHasSupplyVos.add(orderExcuteVo);
						}
					}


					if(jitHasSupplyVos.size()>0){
						Map<String, List<OrderExcuteLineVo>> voGroupMap = jitHasSupplyVos.stream().collect(Collectors.groupingBy(per -> per.getWhCode() + "_" + per.getSupplyChain().getPnCode()));
						for(String key : voGroupMap.keySet()) {
							String[] keyA = key.split("_");
							List<OrderExcuteLineVo> subLineVos = voGroupMap.get(key);
							MoPickingNotice notice = new MoPickingNotice();
							//关联生产订单业务字段
							notice.setProductItemCode(order.getProductItemCode());
							notice.setProductItemName(order.getProductItemName());
							notice.setOrderQuantity(order.getOrderQuantity());
							notice.setProductDrawingNo(order.getProductDrawingNo());
							notice.setMainWorkshop(order.getMainWorkshop());

							notice.setBizOrderNo(order.getBizNo());
							notice.setNoticeDate(new Date());
							notice.setWhCode(keyA[0]);
							notice.setAccessType(accessType);
							notice.setPickingType(context.getPickingType());
							notice.setNoticeStatus(NoticeStatusEnums.NoticeStatus.CREATE.getStatusCode());
							JpaUtil.save(notice);


							int lineNo = 0;
							List<NoticeLine> savedLines = new ArrayList<>();
							for(OrderExcuteLineVo vo : subLineVos) {
								lineNo++;
								NoticeLine line = notice.createLine(vo);
								line.setLineNo(lineNo+"");
								if (itemMap.containsKey(vo.getItemCode())){
									Item item = itemMap.get(vo.getItemCode());
									line.setItemName(item.getItemName());
									line.setItemSpec(item.getItemSpec());
									line.setUnitCode(item.getUnitCode());
									line.setDrawingNo(item.getDrawingNo());
								}
								JpaUtil.save(line);

								//line.setNotice(notice);
								line.setSupplyChain(vo.getSupplyChain());
								savedLines.add(line);
							}

							FeedPlanNotice feedPlanNotice = new FeedPlanNotice();
							feedPlanNotice.setSourcePickingNoticeNo(notice.getNoticeNo());
							feedPlanNotice.setWhCode(notice.getWhCode());
							feedPlanNotice.setNoticeStatus(NoticeStatusEnums.NoticeStatus.DRAFT.getStatusCode());
							feedPlanNotice.setPnCode(savedLines.get(0).getSupplyChain().getPnCode());
							feedPlanNotice.setPnName(savedLines.get(0).getSupplyChain().getSupply().getPnName());
							feedPlanNotice.setNoticeDate(new Date());
							feedPlanNotice.setAccessType("in");
							feedPlanNotice.setPickingType(NoticeStatusEnums.NoticeType.FP_IN.getCode());
							feedPlanNotice.setBizOrderNo(order.getBizNo());
							JpaUtil.save(feedPlanNotice);

							int newlineno = 0;
							for (NoticeLine line:savedLines){
								newlineno++;
								FeedPlanNoticeLine feedPlanNoticeLine = new FeedPlanNoticeLine();
								feedPlanNoticeLine.setNoticeNo(feedPlanNotice.getNoticeNo());
								feedPlanNoticeLine.setSourcePickingNoticeNo(line.getNoticeNo());
								feedPlanNoticeLine.setSourcePickingNoticeLineNo(line.getLineNo());
								feedPlanNoticeLine.setItemCode(line.getItemCode());
								feedPlanNoticeLine.setItemName(line.getItemName());
								feedPlanNoticeLine.setItemSpec(line.getItemSpec());
								feedPlanNoticeLine.setUnitCode(line.getUnitCode());
								feedPlanNoticeLine.setDrawingNo(line.getDrawingNo());
								feedPlanNoticeLine.setQuantity(line.getQuantity());
								feedPlanNoticeLine.setSort(newlineno+"");
								feedPlanNoticeLine.setLineNo(newlineno+"");
								JpaUtil.save(feedPlanNoticeLine);
							}
						}
					}*/
				}
			}
			if(OrderStatusEnums.OrderStatus.PLAN.getStatusCode().equals(order.getOrderStatus())||
					OrderStatusEnums.OrderStatus.ORDERED.getStatusCode().equals(order.getOrderStatus())){
				order.setOrderStatus(OrderStatusEnums.OrderStatus.PROCESSING.getStatusCode());
				order.setExecuteTime(new Date());
				order.setExecutor(SecurityUtils.getLoginUsername());
				JpaUtil.update(order);
			}
			afterExecute(context);
		} else {
			if(CollectionUtils.isEmpty(context.getErrors())) {
				context.addError("前置校验不通过");
			}
		}
	}

	@Override
	public boolean beforeExecute(OrderContext context) {
		Order order = context.getEntity();
		if (order instanceof ManufactureOrder && context.getOrderExcuteVos().size()>0){

			List<OrderExcuteLineVo> orderExcuteVos = context.getOrderExcuteVos();

			//检查jit物料的供应商情况
			Set<String> itemCodeSet = orderExcuteVos.stream().map(OrderExcuteLineVo::getItemCode).collect(Collectors.toSet());
			List<ItemPlanProp> itemPlanPropList = JpaUtil.linq(ItemPlanProp.class).equal("propType", "item").in("code", itemCodeSet).list();
			Map<String, ItemPlanProp> itemPlanPropMap = JpaUtil.index(itemPlanPropList, "code");

			String[] accessTypes = context.getAccessType().split(",");
			//jit物料
			List<OrderExcuteLineVo> jitVos = new ArrayList<>();
			for(String accessType : accessTypes) {
				if (NoticeStatusEnums.NoticeType.MO_M_OUT.getCode().equals(context.getPickingType())
						|| NoticeStatusEnums.NoticeType.MO_M_REOUT.getCode().equals(context.getPickingType())) {
					for (OrderExcuteLineVo vo : orderExcuteVos) {
						//只考虑领料、补料这两种通知单类型，且是出库操作
						if (OrderEnums.AccessType.OUT.getCode().equals(accessType)
								&& itemPlanPropMap.containsKey(vo.getItemCode())
								&& ItemEnums.FeedingMode.JIT.getTypeCode().equals(itemPlanPropMap.get(vo.getItemCode()).getFeedingMode())) {
							jitVos.add(vo);
						}
					}
				}
			}
			if (jitVos.size()>0){
				for(OrderExcuteLineVo orderExcuteVo : jitVos) {
					List<SupplyChain> list = JpaUtil.linq(SupplyChain.class).equal("itemCode", orderExcuteVo.getItemCode()).equal("defaultSupply", CommonEnums.YesNo.YES.getCode()).list();
					if (list.size()==0){
						context.addError("提交数据中行号【"+orderExcuteVo.getBizOrderlineNo()+"】物料【"+orderExcuteVo.getItemCode()+"】属于JIT物料，未指定默认供应商。");
						return false;
					}else if (list.size()>1){
						context.addError("提交数据中行号【"+orderExcuteVo.getBizOrderlineNo()+"】物料【"+orderExcuteVo.getItemCode()+"】属于JIT物料，指定了多个默认供应商，默认供应商只能有一个。");
						return false;
					}
				}
			}
				//校验执行数量
			List<String> orderlinesStr = orderExcuteVos.stream().map(OrderExcuteLineVo::getBizOrderlineNo).collect(Collectors.toList());
			List<ManufactureOrderItem> orderLines = JpaUtil.linq(ManufactureOrderItem.class).equal("bizNo", order.getBizNo()).in("lineNo", orderlinesStr).list();

			NoticeClassVo pickingNoticeClazz = new NoticeClassVo(MoPickingNotice.class, MoPickingNoticeLine.class);//领/补/退
			NoticeClassVo defectiveProductsNoticeClazz = new NoticeClassVo(DefectiveProductsNotice.class, DefectiveProductsNoticeLine.class);//不良品退料
			List<NoticeClassVo> noticeClassVos = new ArrayList<>();
			noticeClassVos.add(pickingNoticeClazz);
			noticeClassVos.add(defectiveProductsNoticeClazz);
			orderLineService.handleBizOrderLineQuantity(orderLines, noticeClassVos, OrderEnums.AccessType.OUT.getCode());
			Map<String, ManufactureOrderItem> orderLineMap = JpaUtil.index(orderLines,"lineNo");
			if(NoticeStatusEnums.NoticeType.MO_M_IN.getCode().equals(type)){//MO_M_IN("15", "生产退料"),
				for(OrderExcuteLineVo orderExcuteVo : orderExcuteVos) {
					// BigDecimal lineQuantity = orderExcuteVo.getLineQuantity();
					BigDecimal quantity = orderExcuteVo.getQuantity();
					String bizOrderlineNo = orderExcuteVo.getBizOrderlineNo();
					ManufactureOrderItem orderLine = orderLineMap.get(bizOrderlineNo);
					if (orderLine!=null){
						BigDecimal actualQuantity = orderLine.getActualQuantity();
						BigDecimal actualRejectQuantity = orderLine.getActualRejectQuantity();
						//BigDecimal planQuantity = orderLine.getPlanQuantity();
						BigDecimal planRejectQuantity = orderLine.getPlanRejectQuantity();
						//退料时，最大可退数量=已执行数量减去已执行退货数量减去计划退货数量，不考虑计划执行数量
						BigDecimal lastMax = actualQuantity.subtract(actualRejectQuantity).subtract(planRejectQuantity);
						if (quantity.compareTo(lastMax)>0){
							context.addError("提交数据中行号【"+bizOrderlineNo+"】执行数量大于最大可执行数量【"+lastMax+"】。");
							return false;
						}
					}
				}
			}else if(NoticeStatusEnums.NoticeType.MO_M_OUT.getCode().equals(type)){//	MO_M_OUT("41", "生产领料"),
				for(OrderExcuteLineVo orderExcuteVo : orderExcuteVos) {
					BigDecimal lineQuantity = orderExcuteVo.getLineQuantity();
					BigDecimal quantity = orderExcuteVo.getQuantity();
					String bizOrderlineNo = orderExcuteVo.getBizOrderlineNo();
					ManufactureOrderItem orderLine = orderLineMap.get(bizOrderlineNo);
					if (orderLine!=null){
						BigDecimal actualQuantity = orderLine.getActualQuantity();
						BigDecimal actualRejectQuantity = orderLine.getActualRejectQuantity();
						BigDecimal planQuantity = orderLine.getPlanQuantity();
						//最大可领：执行行总数量减去实际已领，减去计划领料，加上实际退料数量，不考虑计划退货数量
						BigDecimal lastMax = lineQuantity.subtract(actualQuantity).subtract(planQuantity).add(actualRejectQuantity);
						if (quantity.compareTo(lastMax)>0){
							context.addError("提交数据中行号【"+bizOrderlineNo+"】执行数量大于最大可执行数量【"+lastMax+"】。");
							return false;
						}
					}
				}
			}else{
				return true;//补料不验证
			}
		}
		return true;
	}

	@Override
	public void afterExecute(OrderContext context) {
		
	}

}
